package com.qyer.search.sort;

import static com.qyer.log.WarningLogger.logWarning;
import static com.qyer.search.model.lastminute.SKU.unknownPositionSKU;
import static com.qyer.search.utils.ModelUtils.mergeType1;

import com.qyer.commons.mc.MutableCache;
import com.qyer.search.cache.mutable.MutableCaches;
import com.qyer.search.engine.RecursiveSortTask;
import com.qyer.search.exception.SearchException;
import com.qyer.search.model.SearchParameter;
import com.qyer.search.model.SearchParameterOrigin;
import com.qyer.search.model.SecondComparableTuple2;
import com.qyer.search.model.lastminute.SKU;
import com.qyer.search.model.middle.RecursiveSortResult;
import com.qyer.search.model.result.Type1SearchPackage;
import com.qyer.search.threading.SortingThreadPoolHolder;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 * 根据大类型所对应的顺序字典排序
 * <p/>
 * User: Z J Wu Date: 2016/01/08 Time: 16:48 Package: com.qyer.search.sort
 */
public class Type1Sorter implements SearchResultSorter {

  private SearchParameterOrigin sp;
  private List<Type1SearchPackage> searchPackages;

  public Type1Sorter(SearchParameterOrigin sp, List<Type1SearchPackage> searchPackages) {
    this.sp = sp;
    this.searchPackages = searchPackages;
  }

  public List<Type1SearchPackage> sortSearchPackagesWithThreads() throws SearchException {
    long t1 = System.currentTimeMillis();
    if (CollectionUtils.isEmpty(searchPackages)) {
      return Collections.emptyList();
    }
    MutableCache<Map<Integer, Map<Integer, Integer>>> cache = MutableCaches
      .getInstance().ASSORTED_SKU_ID_POSITION_MAP;
    Map<Integer, Map<Integer, Integer>> dict = cache.getCacheContent();

    List<Type1SearchPackage> sortedPackages = new ArrayList<>(searchPackages.size());
    List<SKU> skus, unknownList;
    int type1, lid;
    Integer position;
    Map<Integer, Integer> positionMap;
    List<SecondComparableTuple2<SKU, Integer>> tuple2List;
    Type1SearchPackage newPackage;
    List<Future<RecursiveSortResult>> futures = new ArrayList<>();

    long t21 = System.currentTimeMillis();
    try {
      for (Type1SearchPackage searchPackage : searchPackages) {
      /*
      * 目前存在小类型, 如1018, 排序字典都当作2667处理的, 这里要把
      * 小类型翻译成2667
      * 但是展示的时候还是分开展示.
      * */
        type1 = searchPackage.getType1();
        positionMap = dict.get(mergeType1(type1));

        if (MapUtils.isEmpty(positionMap)) {
          sortedPackages.add(searchPackage);
          continue;
        }
        System.out.println("positionMapSize:" + positionMap.size());
        skus = searchPackage.getSkus();
        if (CollectionUtils.isEmpty(skus)) {
          continue;
        }
        unknownList = new ArrayList<>();
        tuple2List = new ArrayList<>(skus.size());
        long t11 = System.currentTimeMillis();
        int size = skus.size();
        if(size > RecursiveSortTask.THRESHOLD){
          RecursiveSortTask recursiveSortTask = new RecursiveSortTask(skus, 0, size, positionMap, sp, type1);
          ForkJoinPool service = SortingThreadPoolHolder.getInstance().getForkService();
          futures.add(service.submit(recursiveSortTask));
        }else {
          for (SKU sku : skus) {
            lid = sku.getId();
            position = positionMap.get(lid);
            // 获取位置信息, 放到SecondComparableTuple2准备按二元组的第二元素排序, 不认识的商品不参与排序
            if (position == null) {
              logWarning(unknownPositionSKU(lid), sp, null);
              unknownList.add(sku);
            } else {
              tuple2List.add(new SecondComparableTuple2<>(sku, position));
            }
          }
          long t12 = System.currentTimeMillis();
          System.out.println("sku数量:" + skus.size());
          System.out.println("sku循环时间:" + (t12 - t11));
          Collections.sort(tuple2List);
          System.out.println("小循环排序时间:" + (System.currentTimeMillis() - t12));
          newPackage = new Type1SearchPackage(type1);
          long t13 = System.currentTimeMillis();
          for (SecondComparableTuple2<SKU, Integer> tuple2 : tuple2List) {
            newPackage.addSku(tuple2.getFirst());
          }
          System.out.println("次循环时间:" + (System.currentTimeMillis() - t13));
          // 不认识顺序的商品放到最后
          newPackage.addSkus(unknownList);
          sortedPackages.add(newPackage);
        }
      }
      long t41 = System.currentTimeMillis();
      if(CollectionUtils.isNotEmpty(futures)){
        int size = futures.size();
        for(int i = 0; i < size; i++){
          try{
            RecursiveSortResult recursiveSortResult = futures.get(i).get(3000, TimeUnit.MILLISECONDS);
            Collections.sort(recursiveSortResult.getTuple2List());
            newPackage = new Type1SearchPackage(recursiveSortResult.getType());
            for (SecondComparableTuple2<SKU, Integer> tuple2 : recursiveSortResult.getTuple2List()) {
              newPackage.addSku(tuple2.getFirst());
            }
            newPackage.addSkus(recursiveSortResult.getUnknownList());
            sortedPackages.add(newPackage);
          }catch (Exception e){
            e.printStackTrace();
          }
        }
      }
      System.out.println("线程时间:"+(System.currentTimeMillis() - t41));
    }catch (Exception e){
      e.printStackTrace();
    }
    System.out.println("大循环时间:"+(System.currentTimeMillis() - t21));
    System.out.println("排序：" + (System.currentTimeMillis() - t1));
    return sortedPackages;
  }

  @Override public List<Type1SearchPackage> sortSearchPackages() throws SearchException {
    if (CollectionUtils.isEmpty(searchPackages)) {
      return Collections.emptyList();
    }
    MutableCache<Map<Integer, Map<Integer, Integer>>> cache = MutableCaches
      .getInstance().ASSORTED_SKU_ID_POSITION_MAP;
    Map<Integer, Map<Integer, Integer>> dict = cache.getCacheContent();

    List<Type1SearchPackage> sortedPackages = new ArrayList<>(searchPackages.size());
    List<SKU> skus, unknownList;
    int type1, lid;
    Integer position;
    Map<Integer, Integer> positionMap;
    List<SecondComparableTuple2<SKU, Integer>> tuple2List;
    Type1SearchPackage newPackage;

    for (Type1SearchPackage searchPackage : searchPackages) {
      /*
      * 目前存在小类型, 如1018, 排序字典都当作2667处理的, 这里要把
      * 小类型翻译成2667
      * 但是展示的时候还是分开展示.
      * */
      type1 = searchPackage.getType1();
      positionMap = dict.get(mergeType1(type1));
      if (MapUtils.isEmpty(positionMap)) {
        sortedPackages.add(searchPackage);
        continue;
      }
      skus = searchPackage.getSkus();
      if (CollectionUtils.isEmpty(skus)) {
        continue;
      }
      unknownList = new ArrayList<>(skus.size());
      tuple2List = new ArrayList<>(skus.size());
      for (SKU sku : skus) {
        lid = sku.getId();
        position = positionMap.get(lid);
        // 获取位置信息, 放到SecondComparableTuple2准备按二元组的第二元素排序, 不认识的商品不参与排序
        if (position == null) {
          //logWarning(unknownPositionSKU(lid), sp, null);
          unknownList.add(sku);
        } else {
          tuple2List.add(new SecondComparableTuple2<>(sku, position));
        }
      }
      Collections.sort(tuple2List);
      newPackage = new Type1SearchPackage(type1);
      for (SecondComparableTuple2<SKU, Integer> tuple2 : tuple2List) {
        newPackage.addSku(tuple2.getFirst());
      }
      // 不认识顺序的商品放到最后
      newPackage.addSkus(unknownList);
      sortedPackages.add(newPackage);
    }
    return sortedPackages;
  }

}
